<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>无人机视频直播</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            background: #000;
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            height: 100vh;
            overflow: hidden;
        }
        
        .video-container {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            width: 100vw;
            height: 100vh;
            overflow: hidden;
        }
        
        .video-wrapper {
            max-width: 100%;
            max-height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100%;
            height: 100%;
            position: relative;
        }
        
        video {
            /* 使用视口单位确保响应式显示 */
            max-width: 100vw;
            max-height: 100vh;
            width: 98vw;  /* 略小于100%避免滚动条 */
            height: auto;
            aspect-ratio: 16/9;  /* 设置标准视频比例 */
            object-fit: contain;
            background: #000;
            /* 防闪烁优化 */
            -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
            -webkit-transform: translateZ(0);
            transform: translateZ(0);
            position: relative;
            /* 确保在移动设备上的流畅显示 */
            vertical-align: middle;
        }
        
        /* 添加视频容器的响应式优化 */
        .video-wrapper {
            /* 使用flex布局确保视频居中 */
            display: flex;
            align-items: center;
            justify-content: center;
            /* 使用视口单位设置最小尺寸 */
            min-width: 10vw;
            min-height: 10vh;
            /* 限制最大尺寸以确保控件可见 */
            max-width: 95vw;
            max-height: 95vh;
            /* 添加过渡效果提升用户体验 */
            transition: all 0.3s ease;
        }
        
        /* 添加屏幕方向变化时的特殊处理 */
        @media (orientation: portrait) {
            video {
                /* 在竖屏模式下调整视频比例 */
                aspect-ratio: 3/4;
                width: 95vw;
                height: auto;
            }
        }
        
        @media (orientation: landscape) {
            video {
                /* 在横屏模式下使用标准视频比例 */
                aspect-ratio: 16/9;
                width: 98vw;
                height: auto;
            }
        }
        
        .controls {
            background: rgba(0, 0, 0, 0.8);
            padding: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            transform: translateY(100%);
            transition: transform 0.3s ease;
        }
        
        .video-container:hover .controls {
            transform: translateY(0);
        }
        
        .btn {
            background: #007bff;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        
        .btn:hover {
            background: #0056b3;
        }
        
        .btn:disabled {
            background: #666;
            cursor: not-allowed;
        }
        
        .status {
            color: white;
            font-size: 12px;
            padding: 5px 10px;
            border-radius: 3px;
        }
        
        .status.success {
            background: rgba(40, 167, 69, 0.8);
        }
        
        .status.error {
            background: rgba(220, 53, 69, 0.8);
        }
        
        .status.info {
            background: rgba(23, 162, 184, 0.8);
        }
        
        .loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: white;
            text-align: center;
        }
        
        .loading .spinner {
            border: 4px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top: 4px solid #fff;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto 10px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .error-message {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #ff6b6b;
            text-align: center;
            background: rgba(0, 0, 0, 0.8);
            padding: 20px;
            border-radius: 8px;
            max-width: 80%;
        }
        
        .info-panel {
            position: absolute;
            top: 10px;
            left: 10px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 10px;
            border-radius: 4px;
            font-size: 12px;
            display: none;
        }
        
        .show-info .info-panel {
            display: block;
        }
    </style>
</head>
<body>
    <div class="video-container">
        <video id="videoPlayer" controls autoplay muted playsinline></video>
        
        <div class="loading" id="loading">
            <div class="spinner"></div>
            <div>正在连接视频流...</div>
        </div>
        
        <div class="error-message" id="errorMessage" style="display: none;">
            <h3>播放失败</h3>
            <p id="errorText"></p>
            <button class="btn" onclick="retryPlay()">重试</button>
        </div>
        
        <div class="info-panel" id="infoPanel">
            <div>设备ID: <span id="droneId">-</span></div>
            <div>播放协议: HTTP-FLV</div>
            <div>播放地址: <span id="streamUrl">-</span></div>
            <div>状态: <span id="playStatus">-</span></div>
        </div>
        
        <div class="controls">
            <button class="btn" id="playBtn" onclick="togglePlay()">播放</button>
            <button class="btn" onclick="toggleInfo()">信息</button>
            <div class="status" id="statusText">准备就绪</div>
        </div>
    </div>

    <script src="flv.min.js"></script>
    <script>
        class DroneVideoPlayer {
            constructor() {
                this.video = document.getElementById('videoPlayer');
                this.loading = document.getElementById('loading');
                this.errorMessage = document.getElementById('errorMessage');
                this.errorText = document.getElementById('errorText');
                this.statusText = document.getElementById('statusText');
                this.playBtn = document.getElementById('playBtn');
                
                this.droneId = null;
                this.flvPlayer = null;
                this.streamUrls = null;
                this.isPlaying = false;
                
                this.init();
            }
            
            init() {
                // 从URL参数获取设备ID
                const urlParams = new URLSearchParams(window.location.search);
                this.droneId = urlParams.get('droneId') || urlParams.get('id');
                
                if (!this.droneId) {
                    this.showError('缺少设备ID参数，请在URL中添加 ?droneId=设备ID');
                    return;
                }
                
                document.getElementById('droneId').textContent = this.droneId;
                this.loadStreamUrls();
            }
            
            async loadStreamUrls() {
                try {
                    // 动态获取当前请求的主机地址，使用8002端口（流媒体服务端口）
                    const host = window.location.hostname;
                    const protocol = window.location.protocol;
                    
                    // 优先使用动态地址
                    let flvUrl = `${protocol}//${host}:8002/live/${this.droneId}.flv`;
                    
                    // 如果是特定的主机地址，可以使用已知的可用地址
                    if (host === '172.18.10.143' && this.droneId === 'DJ0001-1') {
                        flvUrl = 'http://172.18.10.143:8002/live/DJ0001-1.flv';
                    }
                    
                    this.streamUrls = {
                        httpFlvUrl: flvUrl
                    };
                    
                    console.log('构建的FLV播放地址:', this.streamUrls.httpFlvUrl);
                    
                    // 在信息面板中显示播放地址
                    document.getElementById('streamUrl').textContent = this.streamUrls.httpFlvUrl;
                    
                    this.startPlay();
                } catch (error) {
                    this.showError('初始化播放器失败: ' + error.message);
                }
            }
            
            startPlay() {
                this.hideError();
                this.showLoading();
                this.playFlv();
            }
            
            playFlv() {
                try {
                    if (!this.streamUrls.httpFlvUrl) {
                        throw new Error('FLV播放地址不可用');
                    }
                    
                    // 清理之前的播放器
                    this.cleanup();
                    
                    if (typeof flvjs !== 'undefined' && flvjs.isSupported()) {
                        // 使用优化的配置减少加载时间和闪烁
                        this.flvPlayer = flvjs.createPlayer({
                            type: 'flv',
                            url: this.streamUrls.httpFlvUrl,
                            isLive: true,              // 启用直播模式
                            enableStashBuffer: false,  // 禁用缓冲以降低延迟
                            stashInitialSize: 1,       // 最小缓冲区大小
                            // 添加以下配置以优化加载速度
                            lazyLoad: false,           // 禁用懒加载
                            autoCleanupSourceBuffer: true, // 自动清理源缓冲区
                            fixAudioTimestampGap: false, // 禁用音频时间戳修复以降低延迟
                            // 提高画面质量的配置
                            seekType: 'range',         // 使用range请求以提高稳定性
                            rangeLoadZeroStart: true,  // 从0开始加载range
                            accurateSeek: true,        // 精确seek以提高播放准确性
                            // 进一步优化画面质量
                            referer: '',               // 设置referer头
                            headers: {                 // 自定义HTTP头
                                'Accept': '*/*',
                                'Cache-Control': 'no-cache'
                            }
                        }, {
                            // 优化加载性能的配置
                            enableWorker: false,       // 禁用Worker以减少初始化时间
                            enableStashBuffer: false,
                            stashInitialSize: 1,
                            // 提高画面质量的配置
                            deferLoadAfterSourceOpen: false, // 立即加载而不是等待sourceopen事件
                            // 防闪烁的关键配置
                            maxBufferLength: 0.5,      // 减少缓冲区长度以降低延迟
                            maxMaxBufferLength: 1,     // 最大缓冲区长度
                            // 解决画面闪烁的配置
                            enableWorkerForMSE: false, // 禁用MSE的Worker以提高兼容性
                            // 优化播放稳定性，减少闪烁
                            liveBufferLatencyChasing: false, // 关闭延迟追踪避免频繁调整
                            autoCleanupMaxBackwardDuration: 3,
                            autoCleanupMinBackwardDuration: 2
                        });
                        
                        this.flvPlayer.attachMediaElement(this.video);
                        
                        // 防闪烁事件处理
                        this.video.addEventListener('loadstart', () => {
                            console.log('开始加载视频');
                        });
                        
                        this.video.addEventListener('loadeddata', () => {
                            console.log('视频数据加载完成');
                            this.hideLoading();
                        });
                        
                        this.video.addEventListener('canplay', () => {
                            console.log('视频可以播放');
                            // 立即播放，减少等待时间
                            this.video.play().catch(e => {
                                console.warn('自动播放失败:', e);
                            });
                        });
                        
                        // 添加加载进度事件
                        this.flvPlayer.on(flvjs.Events.STATISTICS_INFO, (statInfo) => {
                            if (statInfo && statInfo.speed) {
                                this.hideLoading();
                                this.updateStatus('FLV播放中', 'success');
                            }
                        });
                        
                        this.flvPlayer.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
                            console.error('FLV播放错误:', errorType, errorDetail, errorInfo);
                            this.showError(`播放失败: ${errorDetail || errorType}`);
                        });
                        
                        this.flvPlayer.on(flvjs.Events.METADATA_ARRIVED, () => {
                            console.log('媒体元数据到达');
                            this.hideLoading();
                            this.updateStatus('FLV播放中', 'success');
                            this.isPlaying = true;
                            this.updatePlayButton();
                        });
                        
                        // 防闪烁：处理缓冲事件
                        this.video.addEventListener('waiting', () => {
                            console.log('视频缓冲中...');
                            // 不显示Loading，避免闪烁
                        });
                        
                        this.video.addEventListener('playing', () => {
                            console.log('视频正在播放');
                            this.hideLoading();
                        });
                        
                        // 立即开始加载
                        this.flvPlayer.load();
                        
                    } else {
                        throw new Error('浏览器不支持FLV播放');
                    }
                } catch (error) {
                    this.showError('FLV播放失败: ' + error.message);
                }
            }
            
            cleanup() {
                if (this.flvPlayer) {
                    this.flvPlayer.destroy();
                    this.flvPlayer = null;
                }
                
                this.video.pause();
                this.video.src = '';
                this.isPlaying = false;
                this.updatePlayButton();
            }
            
            showLoading() {
                this.loading.style.display = 'block';
                this.errorMessage.style.display = 'none';
            }
            
            hideLoading() {
                this.loading.style.display = 'none';
            }
            
            showError(message) {
                this.hideLoading();
                this.errorText.textContent = message;
                this.errorMessage.style.display = 'block';
                this.updateStatus('播放失败', 'error');
            }
            
            hideError() {
                this.errorMessage.style.display = 'none';
            }
            
            updateStatus(text, type = 'info') {
                this.statusText.textContent = text;
                this.statusText.className = `status ${type}`;
                document.getElementById('playStatus').textContent = text;
            }
            
            updatePlayButton() {
                this.playBtn.textContent = this.isPlaying ? '停止' : '播放';
            }
            
            togglePlay() {
                if (this.isPlaying) {
                    this.cleanup();
                    this.updateStatus('已停止', 'info');
                } else {
                    this.startPlay();
                }
            }
            
            retryPlay() {
                this.startPlay();
            }
        }
        
        // 全局函数
        function togglePlay() {
            player.togglePlay();
        }
        
        function retryPlay() {
            player.retryPlay();
        }
        
        function toggleInfo() {
            document.body.classList.toggle('show-info');
        }
        
        // 初始化播放器
        let player;
        window.onload = function() {
            player = new DroneVideoPlayer();
        };
        
        // 页面可见性处理 - 当页面不可见时停止播放，可见时重新播放以解决延迟问题
        document.addEventListener('visibilitychange', function() {
            if (document.hidden) {
                // 页面隐藏时，停止播放
                if (player && player.isPlaying) {
                    player.cleanup();
                    player.updateStatus('页面隐藏，已暂停', 'info');
                }
            } else {
                // 页面重新可见时，重新开始播放
                if (player) {
                    player.startPlay();
                    player.updateStatus('页面恢复，重新连接...', 'info');
                }
            }
        });
        
        // 防止iframe中的上下文菜单
        document.addEventListener('contextmenu', function(e) {
            e.preventDefault();
        });
        
        // 处理窗口大小变化 - 添加防抖处理
        let resizeTimer;
        window.addEventListener('resize', function() {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(function() {
                adjustVideoSize();
            }, 50); // 50ms的防抖延迟
        });
        
        // 调整视频尺寸的函数
        function adjustVideoSize() {
            var video = document.getElementById('videoPlayer');
            var container = document.querySelector('.video-container');
            
            // 确保视频在容器中正确显示
            if (video && container) {
                // 获取容器和视频的尺寸
                var containerWidth = container.clientWidth;
                var containerHeight = container.clientHeight;
                
                // 设置视频的最大尺寸
                video.style.maxWidth = containerWidth + 'px';
                video.style.maxHeight = containerHeight + 'px';
                
                // 确保视频保持原始宽高比
                video.style.width = 'auto';
                video.style.height = 'auto';
                
                // 强制重绘
                var display = video.style.display;
                video.style.display = 'none';
                video.offsetHeight; // 触发重排
                video.style.display = display;
            }
        }
    </script>
</body>
</html>